"""Cif file import:
imports all cif type files into a cif class object, and provides various methods of this cif class:"""

import os

class Cif_file_class(object):
    """Class encapsulating a cif object. Takes in an argument the full filename for the cif."""
    
    def __init__(self,cif_filename):
        """Instantiate the class: read in the cif file,
        parse it and create a dictionary of values from it, 
        as well as a list of the cif values."""
        self.cif_filename = cif_filename
        self.cif_list = self.cif_to_list()
        self.cif_dict = self.ciflist_to_dict()
        self.loop_number = self.loop_extraction()[0]
        self.loop_list = self.loop_extraction()[1]
        
    def cif_to_list(self):
        """A function to import a cif and return it as a list of the lines. 
        The cif_name must be the include the full path. It strips out lines 
        that are whitespace and only comments and removes endline characters."""
        
        cif_list = []
        cif_open = open(self.cif_filename, 'r')
        for line in cif_open:
            if line.split() == []:
                pass
            elif (line.split())[0][0] == '#':
                pass
            else:
                cif_list.append(str(line[:-1]))
        cif_open.close()
        return(cif_list)
    
    def ciflist_to_dict(self):
        """A function to convert a cif list to a dictionary. Each cif item 
        becomes a dictionary item with the cif value callable by its cif input. 
        Loop items are linked as the full loop header. """
        
        def loop_comprehension(cif_list):
            """Internal funciton to do loop comprehension. Removes the entire loop 
            structure from the top of the list."""
            
            n = 0
            m = 0
            k = 0
            header_temp = []
            data_temp = []
            data_temp_combine = ''
            header_temp_combine = ''
            
            while k == 0:
                if m == 0:
                    header_temp.append((cif_list[0].strip()))
                    cif_list.pop(0)
                    m = 1
                elif n == 0:
                    if (cif_list[0].strip())[0] == '_':
                        header_temp.append((cif_list[0].strip()))
                        cif_list.pop(0)
                    else:
                        n = 1
                        data_temp.append(cif_list[0])
                        cif_list.pop(0)
                else:
                    if cif_list == [] or cif_list[0][0] == '_' or (cif_list[0].strip())[0:5] == 'loop_':
                        header_temp_combine = ' \n '.join(header_temp)
                        data_temp_combine = '\n' + '\n'.join(data_temp)
                        cif_dict[header_temp_combine] = data_temp_combine
                        header_temp = []
                        data_temp = []
                        header_temp_combine = ''
                        data_temp_combine = ''
                        k = 1
                    elif cif_list[0].strip() == '':
                        cif_list.pop(0)
                    else:
                        data_temp.append(cif_list[0])
                        cif_list.pop(0)
                            
        def normal_comprehension(cif_list):
            """Internal function to do normal comprehension."""
            
            n = 0
            m = 0
            header_temp = ''
            data_temp = ''
            data_temp_list = []
            
            while m == 0:
                if n == 0:
                    line_split = (cif_list[0]).split()
                    header_temp = line_split[0]
                    if len(line_split) > 1 :
                        data_temp = ' '.join(line_split[1:])
                        cif_dict[header_temp] = data_temp
                        cif_list.pop(0)
                        data_temp = ''
                        header_temp = ''
                        m = 1
                    else:
                        cif_list.pop(0)
                        n = 1
                elif n == 1:
                    if (cif_list[0].split())[0] == ';':
                        data_temp_list.append(cif_list[0])
                        cif_list.pop(0)
                        n = 2
                    else:
                        data_temp = '\n' + ' '.join((cif_list[0].split()))
                        cif_dict[header_temp] = data_temp
                        header_temp = ''
                        data_temp = ''
                        cif_list.pop(0)
                        m = 1
                else:
                    if (cif_list[0].split())[0] == ';':
                        data_temp_list.append(';')
                        data_temp = '\n' + '\n'.join(data_temp_list)
                        cif_dict[header_temp] = data_temp
                        data_temp = ''
                        header_temp = ''
                        data_temp_list = []
                        cif_list.pop(0)
                        m = 1
                    else:
                        data_temp_list.append(cif_list[0])
                        cif_list.pop(0)
                    
        def data_comprehension(cif_list):
            """Internal function to deal with data_ items."""
            cif_dict['data_'] = cif_list[0][5:]
            cif_list.pop(0)
            
        def olex2_fix(cif_dict_initial):
            """
            Converts OLEX2 specific or created cif data items into to version 
            expected by the script.
            """
            if cif_dict_initial.has_key('_space_group_crystal_system'):
                cif_dict_initial['_symmetry_cell_setting'] = cif_dict_initial['_space_group_crystal_system']
            if cif_dict_initial.has_key('_space_group_name_H-M_alt'):
                cif_dict_initial['_symmetry_space_group_name_H-M'] = cif_dict_initial['_space_group_name_H-M_alt']
            if cif_dict_initial.has_key('_diffrn_standards_decay_%'):
                pass
            else:
                cif_dict_initial['_diffrn_standards_decay_%'] = '?'
            
        cif_dict = dict()
        cif_list = self.cif_to_list()
                    
        while cif_list != []:
        
            if cif_list[0][0:5] == 'loop_':
            
                loop_comprehension(cif_list)
            
            elif cif_list[0][0:5] == 'data_':
            
                data_comprehension(cif_list)
            
            elif cif_list[0][0] == '_':
            
                normal_comprehension(cif_list)
            
            else:
                print('Something missed!')
                print(cif_list[0])
                break

        olex2_fix(cif_dict)
            
        return(cif_dict)
    
    def cif_combine(self, added_cif_dict):
        """Combines another cif dictionary into the current cif dictionary.
        Updates the current cif dictionary."""
        for key in added_cif_dict:
            self.cif_dict[key] = added_cif_dict[key]
            
    def loop_extraction(self):
        """Extracts loop information into the loop data form: TBD"""
        
        loop_list_temp = []
        for item in self.cif_dict.keys():
            if item[0:5].lower() == 'loop_':
                loop_list_temp.append(item)
                
        if loop_list_temp == []:
            loop_number = 0
            return [loop_number, loop_list_temp]
        else:
            loop_number = len(loop_list_temp)
            
        for item in loop_list_temp:
            item = item.lstrip()
            
        
            